#include "TM1650.h"
#include <ch32f10x.h>

#define TSCL_1 GPIO_SetBits(GPIOA, GPIO_Pin_6)
#define TSCL_0 GPIO_ResetBits(GPIOA, GPIO_Pin_6)

#define TSDA_1 GPIO_SetBits(GPIOA, GPIO_Pin_7)
#define TSDA_0 GPIO_ResetBits(GPIOA, GPIO_Pin_7)

#define TSDA_IN GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7)

#define TMZ 1

extern void delay(uint32_t dly);

const unsigned char BCA[] = {0xEB, 0x09, 0xE5, 0xAD, 0x0F, 0xAE, 0xEE, 0x89, 0xEF, 0xAF, 0xCF, 0x6E, 0xE2, 0x6D, 0xE6, 0xC6, 0x00};
// 0  	1	   2    3    4    5    6    7    8    9    A    b    C    d    E    F   空
const unsigned char BCB[] = {0xFB, 0x19, 0xF5, 0xBD, 0x1F, 0xBE, 0xFE, 0x99, 0xFF, 0xBF, 0xDF, 0x7E, 0xF2, 0x7D, 0xF6, 0xD6, 0x00};
// 0.   1.	  2.   3.   4.   5.   6.   7.   8.   9.   A.   b.   C.   d.   E.   F.   空
const unsigned char BCN[] = {0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x81, 0x41, 0x21, 0x11, 0x09, 0x05, 0x03}; // 序号灯
                                                                                                                              // 0    1    2	 3     4    5    6    7    8    9   10   11   12   13   14   15

#define Backlight1 0x11
#define Backlight2 0x21
#define Backlight3 0x31
#define Backlight4 0x41
#define Backlight5 0x51
#define Backlight6 0x61
#define Backlight7 0x71
#define Backlight8 0x01
#define GR1 0x68
#define GR2 0x6A
#define GR3 0x6C
#define GR4 0x6E

unsigned char KI;
unsigned char KS;

#define Jitters 15         // X消抖时间
#define KLS 4              // 按键消抖短按
#define KLM 49             // 按键消抖中按
#define KLL 249            // 按键消抖长按
#define Setup_Timeout 8000 // 设置超时

unsigned char Refresh_Pronto; // 立即刷新
unsigned int T_Dis;
unsigned char Dis_Order;
unsigned char Twinkle_State;
unsigned char T_Flicker;
unsigned char Key_TM;
unsigned char Key_Bit;
unsigned char Dis_Order;
unsigned char K1_Do; // 执行否
unsigned char K2_Do; // 执行否
unsigned char K3_Do; // 执行否
unsigned int Setup_ReturnT;
unsigned int Key_L;        // 按键消抖计时
unsigned char Setup_State; // 设置状态

unsigned char TMDS; // 是一个全局变量，用于存储 TM1650 模块的数据

void SDA_Set(unsigned char IOS)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    if (IOS)
    {
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;    
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_2; 
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    }
    else
    {
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_2;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    }
}

/**
 * @brief 启动 TM1650 通信
 *
 * 该函数通过将时钟线（TSCL）拉高，数据线（TSDA）拉高，然后再将数据线拉低来启动 TM1650 通信。
 * 最后，函数会延迟一段时间以确保通信启动。
 */
void TM1650_START(void)
{
    // 拉高时钟线
    TSCL_1;
    // 拉高数据线
    TSDA_1;
    // 延迟一段时间
    delay(TMZ);
    // 拉低数据线
    TSDA_0;
    // 延迟一段时间
    delay(TMZ);
    // 拉低时钟线
    TSCL_0;
}

/**
 * @brief 停止 TM1650 通信
 *
 * 该函数通过将时钟线（TSCL）拉高，数据线（TSDA）拉低，然后再将数据线拉高来停止 TM1650 通信。
 * 最后，函数会延迟一段时间以确保通信停止。
 */
void TM1650_STOP(void)
{
    // 拉高时钟线
    TSCL_1;
    // 拉低数据线
    TSDA_0;
    // 延迟一段时间
    delay(TMZ);
    // 拉高数据线
    TSDA_1;
    // 延迟一段时间
    delay(TMZ);
}

void TM1650_write(unsigned char shuju)
{
    unsigned char i;
    for (i = 0; i < 8; i++)
    {
        if (shuju & 0x80)
        {
            TSDA_1;
        }
        else
        {
            TSDA_0;
        }
        delay(TMZ);
        TSCL_1;
        shuju <<= 1;
        delay(TMZ);
        TSCL_0;
    }
    TSDA_1;
    delay(TMZ);
    TSCL_1;
    delay(TMZ);
    TSCL_0;
}

void TM1650_send(unsigned char date1, unsigned char date2)
{
    TM1650_START();
    TM1650_write(date1);
    TM1650_write(date2);
    TM1650_STOP();
}

void TM1650_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_2;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

// 读按键命令
unsigned char Read_Key_1650(void)
{
    unsigned char dat, i;
    TM1650_START();
    TM1650_write(0x49); // 读按键指令

    TSDA_1;
    dat = 0;
    SDA_Set(1);
    for (i = 0; i < 8; i++)
    {
        TSCL_1; // 时钟上沿
        dat <<= 1;
        if (TSDA_IN)
            dat++;
        TSCL_0;
    }
    SDA_Set(0);
    TSDA_1;
    TSCL_1;
    TSCL_0;

    TM1650_STOP();

    return dat;
}


unsigned char Dat_To_Key(void)
{
    unsigned char dat, k;
    dat = Read_Key_1650();
    switch (dat)
    {
    case 68:
        k = 2;
        break;
    case 69:
        k = 1;
        break;
    case 70:
        k = 3;
        break;
    default:
        k = 0;
        break;
    }
    return k;
}

// 显示关闭
void DIS_Off(void)
{
    TM1650_send(0x48, 0); // 关闭显示
}

// 显示变量
void DIS_TA(unsigned char E, unsigned int S)
{
    unsigned int dis_data;
    unsigned char g, s, b, q;
    dis_data = S;
    q = dis_data / 1000;
    b = (dis_data - q * 1000) / 100;
    s = (dis_data - q * 1000 - b * 100) / 10;
    g = dis_data % 10;

    TM1650_send(0x48, Backlight8); // 开启显示、N级亮度1-8

    TM1650_send(GR1, BCA[b]);
    TM1650_send(GR2, BCA[s]);
    TM1650_send(GR3, BCA[g]);

    if (Twinkle_State && Dis_Order > 4 && Dis_Order < 10)
    {
        TM1650_send(GR4, 0);
    }
    else
    {
        TM1650_send(GR4, BCN[E]);
    }
}

// 按键测试显示
void DIS_KS(void)
{
    KS = Read_Key_1650();
    KI++;
    if (KI > 15)
    {
        KI = 0;
    }
    DIS_TA(KI, KS);
}
void DIS_TM1650(void)
{
    switch (Dis_Order)
    {
    case 1:
        DIS_TA(Dis_Order, Fault_Status);
        break;
    case 2:
        DIS_TA(Dis_Order, Module_XStatus);
        break;
    case 3:
        DIS_TA(Dis_Order, Module_YStatus);
        break;
    case 4:
        DIS_TA(Dis_Order, Start_Delay / 10);
        break;
    case 5:
        DIS_TA(Dis_Order, Handover_Delay);
        break;
    case 6:
        DIS_TA(Dis_Order, Restart_Delay);
        break;
    case 7:
        DIS_TA(Dis_Order, Contactor_Delay);
        break;
    case 8:
        DIS_TA(Dis_Order, Minimum_Time);
        break;
    case 9:
        DIS_TA(Dis_Order, Work_Mode);
        break;
    case 10:
        DIS_TA(Dis_Order, Product_Version);
        break;
    case 11:
        DIS_TA(Dis_Order, Product_ID);
        break;
    case 12:
        DIS_TA(Dis_Order, Manufacture_Date);
        break;

    default:
        Dis_Order = 1;
        break;
    }
}
